package com.iot.common.core.domain;

import com.iot.common.core.domain.entity.SysDept;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * @author caoning
 */
public class Node {
    private Long id;
    private Long pid;
    private String value;
    private String label;
    private Object obj;
    private Map<String, Object> ext;
    private List<Node> children = new ArrayList<Node>();

    public Node() {
        super();
    }

    public Node(Long id) {
        this.id = id;
    }

    private static <T> Object invokeValue(T t, String field){
        try {
            Field declaredField = t.getClass().getDeclaredField(field);
            declaredField.setAccessible(true);
            Object value = declaredField.get(t);
            return value;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> List<Node> nodeList(List<T> list, String idField, String valueField, String labelField) {
        List<Node> nodes = new ArrayList<Node>();
        for(T t : list){
            Node node = new Node();
            Object id = invokeValue(t, idField);
            node.setIdObj(id);
            Object value = invokeValue(t, valueField);
            node.setValObj(value);
            Object label = invokeValue(t, labelField);
            node.setLabelObj(label);
            nodes.add(node);
        }
        return nodes;
    }

    private void setIdObj(Object o) {
        if(o != null){
            if(o instanceof Number){
                this.setId((Long) o);
            }else{
                try{
                    Long.parseLong(o.toString());
                }catch (Exception e){}
            }
        }
    }

    private void setValObj(Object o) {
        if(o != null){
            this.setValue(o.toString());
        }
    }

    private void setLabelObj(Object o) {
        if(o != null){
            this.setLabel(o.toString());
        }
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getPid() {
        return pid;
    }

    public void setPid(Long pid) {
        this.pid = pid;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }

    public Map<String, Object> getExt() {
        return ext;
    }

    public void setExt(Map<String, Object> ext) {
        this.ext = ext;
    }

    public List<Node> getChildren() {
        return children;
    }

    public void setChildren(List<Node> children) {
        this.children = children;
    }

    public static Node list2Node(List<Node> list, Node root){
        List<Node> nextRecurrenceList = new ArrayList<Node>();
        for(Node org : list){
            if(org.getPid().equals(root.getId())){
                root.getChildren().add(org);
            }else{
                nextRecurrenceList.add(org);
            }
        }
        List<Node> children = root.getChildren();
        if(nextRecurrenceList.size() > 0 && children != null){
            root.setChildren(new ArrayList<Node>());
            for(Node org : children){
                root.getChildren().add(list2Node(nextRecurrenceList, org));
            }
        }
        return root;
    }

    public static Node sysDeptList2Node(List<SysDept> sysDeptList){
        Node root = new Node(0L);
        return Node.list2Node(Node.copySysDeptList(sysDeptList), root);
    }

    public static List<Node> copySysDeptList(List<SysDept> sysDeptList){
        List<Node> nodes = new ArrayList<Node>();
        for(SysDept sysDept : sysDeptList){
            Node node = new Node();
            node.setId(sysDept.getDeptId());
            node.setPid(sysDept.getParentId());
            node.setLabel(sysDept.getDeptName());
            node.setObj(sysDept);
            nodes.add(node);
        }
        return nodes;
    }
}
